<template>
	<div class="schedule-preview">
		<div class="preview-header" v-if="title">
			<div class="header-left">
				<i class="_wtmicon _wtmicon-wxbzhanghu"></i>
				<span>{{ title || '排班预览' }}</span>
			</div>
			<div class="header-right" v-if="!readonly">
				<el-button size="small" @click="goToCurrentMonth" :disabled="isLoading" class="quick-nav-btn">回到当月</el-button>
				<el-button size="small" @click="goToToday" :disabled="isLoading" class="quick-nav-btn">回到今天</el-button>
			</div>
		</div>

		<!-- 月份年份导航栏 -->
		<div class="month-navigator" v-if="!readonly">
			<div class="nav-controls">
				<el-button :icon="ArrowLeft" circle size="small" @click="previousMonth" :disabled="isLoading" class="nav-btn"></el-button>

				<div class="current-period">
					<span class="period-text">{{ currentYear }}年{{ currentMonth + 1 }}月</span>
					<span class="period-title">- 员工排班</span>
				</div>

				<el-button :icon="ArrowRight" circle size="small" @click="nextMonth" :disabled="isLoading" class="nav-btn"></el-button>
			</div>
		</div>

		<!-- 只读模式下的月份显示 -->
		<div v-else class="readonly-month-display">
			<div class="current-period">
				<span class="period-text">{{ currentYear }}年{{ currentMonth + 1 }}月</span>
				<span class="period-title">- 员工排班</span>
			</div>
		</div>

		<div class="preview-content">
			<!-- 排班类型选择 -->
			<div v-if="showTypeSelector" class="type-selector mb-3">
				<el-radio-group v-model="localShiftType" @change="onShiftTypeChange" :disabled="isLoading">
					<el-radio v-for="pattern in availablePatterns" :key="pattern.name" :label="pattern.name">
						{{ pattern.displayName }}
					</el-radio>
				</el-radio-group>
			</div>

			<!-- 工作日期选择 -->
			<div v-if="showDateSelector" class="date-selector mb-3">
				<el-date-picker
					v-model="localWorkDate"
					type="date"
					placeholder="请选择工作日期"
					format="YYYY-MM-DD"
					value-format="YYYY-MM-DD"
					class="width100"
					@change="onWorkDateChange"
					:disabled="isLoading"
				></el-date-picker>
			</div>

			<!-- 加载状态 -->
			<div v-if="isLoading" class="loading-container">
				<el-skeleton :rows="8" animated />
			</div>

			<!-- 排班网格 -->
			<div v-else-if="scheduleData && Object.keys(scheduleData).length > 0" class="schedule-grid">
				<div v-for="(shiftType, date) in scheduleData" :key="date" class="schedule-item" :class="getScheduleItemClass(shiftType)">
					<div class="schedule-date">{{ formatDate(date) }}</div>
					<div class="schedule-type">{{ shiftType }}</div>
					<div class="schedule-weekday">{{ getWeekday(date) }}</div>
				</div>
			</div>

			<!-- 无数据提示 -->
			<div v-else class="no-schedule">
				<span>{{ noDataText || '暂无排班数据' }}</span>
			</div>
		</div>
	</div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, nextTick } from 'vue';
import { ArrowLeft, ArrowRight } from '@element-plus/icons-vue';
import {
	calculateMonthlySchedule,
	getScheduleItemClass as getScheduleItemClassUtil,
	getShiftTypeConfig,
	getShiftPatternConfig,
	getAvailableShiftPatterns,
	getAvailableShiftTypes,
	applyShiftTagMapping,
} from '/@/utils/scheduleCalculator';

interface Props {
	// 排班类型：'三班倒' | '两班倒'
	shiftType?: string;
	// 工作日期
	workDate?: string;
	// 班次标签
	shiftTag?: string;
	// 班次序列，如 ["A", "B", "休"] 或 ["班", "休"]
	shiftSequence?: string[];
	// 是否显示类型选择器
	showTypeSelector?: boolean;
	// 是否显示日期选择器
	showDateSelector?: boolean;
	// 标题
	title?: string;
	// 无数据提示文本
	noDataText?: string;
	// 是否自动计算
	autoCalculate?: boolean;
	// 防抖延迟时间（毫秒）
	debounceDelay?: number;
	// 是否只读模式
	readonly?: boolean;
}

interface Emits {
	(e: 'update:shiftType', value: string): void;
	(e: 'update:workDate', value: string): void;
	(e: 'scheduleChange', data: Record<string, string>): void;
	(e: 'loadingChange', loading: boolean): void;
}

const props = withDefaults(defineProps<Props>(), {
	showTypeSelector: false,
	showDateSelector: false,
	title: '排班预览',
	noDataText: '暂无排班数据',
	autoCalculate: true,
	debounceDelay: 300,
	readonly: false,
});

const emit = defineEmits<Emits>();

// 本地状态
const localShiftType = ref(props.shiftType || '');
const localWorkDate = ref(props.workDate || '');
const localShiftTag = ref(props.shiftTag || '');
const scheduleData = ref<Record<string, string>>({});
const isLoading = ref(false);
let debounceTimer: NodeJS.Timeout | null = null;

// 月份年份导航状态
const currentYear = ref(new Date().getFullYear());
const currentMonth = ref(new Date().getMonth());

// 班次类型配置
const availablePatterns = ref(getAvailableShiftPatterns());
const currentPattern = ref(getShiftPatternConfig(localShiftType.value));

// 防抖函数
const debounce = (func: Function, delay: number) => {
	return (...args: any[]) => {
		if (debounceTimer) {
			clearTimeout(debounceTimer);
		}
		debounceTimer = setTimeout(() => {
			func.apply(null, args);
		}, delay);
	};
};

// 监听外部属性变化
watch(
	() => props.shiftType,
	(newVal) => {
		if (newVal !== localShiftType.value) {
			localShiftType.value = newVal || '';
		}
	}
);

watch(
	() => props.workDate,
	(newVal) => {
		if (newVal !== localWorkDate.value) {
			localWorkDate.value = newVal || '';
		}
	}
);

watch(
	() => props.shiftTag,
	(newVal) => {
		if (newVal !== localShiftTag.value) {
			localShiftTag.value = newVal || '';
			// 班次标签变化时，如果启用了自动计算，立即重新计算排班
			if (props.autoCalculate && localShiftType.value && localWorkDate.value) {
				calculateSchedule();
			}
		}
	}
);

// 计算排班
const calculateSchedule = async () => {
	if (!localShiftType.value || !localWorkDate.value) {
		scheduleData.value = {};
		emit('scheduleChange', {});
		emit('loadingChange', false);
		return;
	}

	try {
		isLoading.value = true;
		emit('loadingChange', true);

		// 使用 nextTick 确保 DOM 更新后再计算
		await nextTick();

		// 从工作日期中提取年月信息
		const workDateObj = new Date(localWorkDate.value);
		const targetYear = workDateObj.getFullYear();
		const targetMonth = workDateObj.getMonth();

		// 使用工具函数计算排班，将班次标签和班次序列作为参数传递
		let result = calculateMonthlySchedule({
			shiftType: localShiftType.value as '三班倒' | '两班倒' | '上一休二',
			workDate: localWorkDate.value,
			shiftTag: localShiftTag.value, // 传递班次标签参数
			shiftSequence: props.shiftSequence, // 传递班次序列
			year: targetYear, // 指定要计算的年份
			month: targetMonth, // 指定要计算的月份
		});

		// 不再需要应用标签映射，因为班次标签已经在计算函数中处理了
		// if (localShiftTag.value && Object.keys(result).length > 0) {
		// 	result = applyShiftTagMapping(result, localShiftTag.value);
		// }

		scheduleData.value = result;

		// 触发事件
		emit('scheduleChange', scheduleData.value);
	} catch (error) {
		console.error('排班计算失败:', error);
		scheduleData.value = {};
	} finally {
		isLoading.value = false;
		emit('loadingChange', false);
	}
};

// 防抖后的计算函数
const debouncedCalculate = debounce(calculateSchedule, props.debounceDelay);

// 排班类型变化处理
const onShiftTypeChange = (value: string) => {
	localShiftType.value = value;
	// 立即更新班次模式配置
	currentPattern.value = getShiftPatternConfig(value);
	emit('update:shiftType', value);
	// 班次标签配置变化后立即计算
	if (props.autoCalculate) {
		// 强制立即计算，不使用防抖
		calculateSchedule();
	}
};

// 工作日期变化处理
const onWorkDateChange = (value: string) => {
	localWorkDate.value = value;
	emit('update:workDate', value);

	// 更新当前年月显示
	if (value) {
		const dateObj = new Date(value);
		currentYear.value = dateObj.getFullYear();
		currentMonth.value = dateObj.getMonth();
	}

	if (props.autoCalculate) {
		// 日期变化时立即计算，不使用防抖
		calculateSchedule();
	}
};

// 格式化日期显示
const formatDate = (dateStr: string) => {
	const date = new Date(dateStr);
	const month = date.getMonth() + 1;
	const day = date.getDate();
	return `${month}/${day}`;
};

// 获取星期几
const getWeekday = (dateStr: string) => {
	const date = new Date(dateStr);
	const weekdays = ['日', '一', '二', '三', '四', '五', '六'];
	return `周${weekdays[date.getDay()]}`;
};

// 获取排班项样式类
const getScheduleItemClass = (shiftType: string) => {
	return getScheduleItemClassUtil(shiftType);
};

// 手动计算排班（供外部调用）
const calculate = () => {
	calculateSchedule();
};

// 强制刷新排班数据（用于班次标签变化时）
const refreshSchedule = () => {
	if (localShiftType.value && localWorkDate.value) {
		calculateSchedule();
	}
};

// 获取排班数据
const getScheduleData = () => {
	return scheduleData.value;
};

// 月份导航方法
const previousMonth = () => {
	if (currentMonth.value === 0) {
		currentMonth.value = 11;
		currentYear.value--;
	} else {
		currentMonth.value--;
	}
	updateScheduleForCurrentPeriod();
};

const nextMonth = () => {
	if (currentMonth.value === 11) {
		currentMonth.value = 0;
		currentYear.value++;
	} else {
		currentMonth.value++;
	}
	updateScheduleForCurrentPeriod();
};

const updateScheduleForCurrentPeriod = () => {
	if (localShiftType.value && localWorkDate.value) {
		// 使用当前选择的年月重新计算排班
		calculateScheduleForPeriod(currentYear.value, currentMonth.value);
	}
};

// 回到当月
const goToCurrentMonth = () => {
	const now = new Date();
	currentYear.value = now.getFullYear();
	currentMonth.value = now.getMonth();

	// 如果启用了自动计算，重新计算排班
	if (props.autoCalculate && localShiftType.value && localWorkDate.value) {
		calculateScheduleForPeriod(currentYear.value, currentMonth.value);
	}
};

// 回到今天
const goToToday = () => {
	const today = new Date();
	const todayStr = today.toISOString().split('T')[0]; // 格式化为 YYYY-MM-DD

	// 更新工作日期
	localWorkDate.value = todayStr;
	emit('update:workDate', todayStr);

	// 更新当前年月显示
	currentYear.value = today.getFullYear();
	currentMonth.value = today.getMonth();

	// 如果启用了自动计算，重新计算排班
	if (props.autoCalculate && localShiftType.value) {
		calculateSchedule();
	}
};

const calculateScheduleForPeriod = async (year: number, month: number) => {
	if (!localShiftType.value || !localWorkDate.value) {
		return;
	}

	try {
		isLoading.value = true;
		emit('loadingChange', true);

		await nextTick();

		// 使用指定的年月计算排班
		let result = calculateMonthlySchedule({
			shiftType: localShiftType.value as '三班倒' | '两班倒' | '上一休二',
			workDate: localWorkDate.value,
			shiftTag: localShiftTag.value,
			year: year,
			month: month,
		});

		scheduleData.value = result;

		emit('scheduleChange', scheduleData.value);
	} catch (error) {
		console.error('排班计算失败:', error);
		scheduleData.value = {};
	} finally {
		isLoading.value = false;
		emit('loadingChange', false);
	}
};

// 暴露方法给父组件
defineExpose({
	calculate,
	getScheduleData,
	refreshSchedule,
	previousMonth,
	nextMonth,
	goToCurrentMonth,
	goToToday,
	currentYear,
	currentMonth,
});

// 监听属性变化自动计算
watch(
	[localShiftType, localShiftTag],
	() => {
		if (props.autoCalculate) {
			// 使用防抖计算，避免频繁调用
			debouncedCalculate();
		}
	},
	{ immediate: false }
);

// 单独监听工作日期变化，确保日期变化时立即重新计算
watch(
	localWorkDate,
	(newVal, oldVal) => {
		if (newVal !== oldVal && props.autoCalculate && localShiftType.value && newVal) {
			// 日期变化时立即计算，不使用防抖
			calculateSchedule();
		}
	},
	{ immediate: false }
);

// 监听班次模式配置变化，确保班次标签更新时重新计算
watch(
	currentPattern,
	() => {
		if (props.autoCalculate && localShiftType.value && localWorkDate.value) {
			// 班次标签配置变化时立即计算，不使用防抖
			calculateSchedule();
		}
	},
	{ immediate: false }
);

// 初始化时计算
onMounted(() => {
	// 初始化当前年月
	if (localWorkDate.value) {
		const dateObj = new Date(localWorkDate.value);
		currentYear.value = dateObj.getFullYear();
		currentMonth.value = dateObj.getMonth();
	}

	if (props.autoCalculate && localShiftType.value && localWorkDate.value) {
		calculateSchedule();
	}
});
</script>

<style scoped>
.schedule-preview {
	border: 1px solid var(--el-border-color-light);
	border-radius: 8px;
	background: var(--el-bg-color);
	box-shadow: var(--el-box-shadow-light);
}

.preview-header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 12px 16px;
	background: var(--el-fill-color-light);
	border-bottom: 1px solid var(--el-border-color-light);
	border-radius: 8px 8px 0 0;
}

.header-left {
	display: flex;
	align-items: center;
}

.header-right {
	display: flex;
	gap: 8px;
}

.preview-header i {
	margin-right: 8px;
	color: var(--el-color-primary);
}

.preview-header span {
	font-weight: 500;
	color: var(--el-text-color-primary);
}

/* 月份导航栏样式 */
.month-navigator {
	background: var(--el-fill-color-blank);
	border-bottom: 1px solid var(--el-border-color-light);
	padding: 20px 16px;
	position: relative;
}

.nav-controls {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 20px;
	margin-bottom: 16px;
}

.nav-btn {
	background: var(--el-color-info);
	border-color: var(--el-color-info);
	color: white;
	transition: all 0.3s ease;
}

.nav-btn:hover:not(:disabled) {
	background: var(--el-color-info-dark-2);
	border-color: var(--el-color-info-dark-2);
	transform: scale(1.05);
}

.nav-btn:disabled {
	background: var(--el-color-info-light-3);
	border-color: var(--el-color-info-light-3);
	cursor: not-allowed;
}

.current-period {
	display: flex;
	align-items: center;
	gap: 8px;
}

.period-text {
	font-size: 18px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}

.period-title {
	font-size: 16px;
	font-weight: 500;
	color: var(--el-text-color-regular);
}

/* 快速导航按钮样式 - 重新设计 */
.quick-nav-btn {
	background: linear-gradient(135deg, var(--el-color-primary), var(--el-color-primary-light-3));
	border: none;
	color: white;
	font-size: 12px;
	font-weight: 500;
	padding: 6px 16px;
	border-radius: 16px;
	transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
	box-shadow: 0 2px 8px rgba(64, 158, 255, 0.15);
	position: relative;
	overflow: hidden;
	height: 28px;
	line-height: 1;
}

.quick-nav-btn::before {
	content: '';
	position: absolute;
	top: 0;
	left: -100%;
	width: 100%;
	height: 100%;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
	transition: left 0.5s;
}

.quick-nav-btn:hover:not(:disabled) {
	background: linear-gradient(135deg, var(--el-color-primary-dark-2), var(--el-color-primary));
	transform: translateY(-1px);
	box-shadow: 0 4px 15px rgba(64, 158, 255, 0.3);
}

.quick-nav-btn:hover:not(:disabled)::before {
	left: 100%;
}

.quick-nav-btn:active {
	transform: translateY(0);
	box-shadow: 0 2px 10px rgba(64, 158, 255, 0.25);
}

.quick-nav-btn:disabled {
	background: linear-gradient(135deg, var(--el-color-primary-light-5), var(--el-color-primary-light-7));
	cursor: not-allowed;
	transform: none;
	box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
}

.preview-content {
	padding: 16px;
}

.type-selector,
.date-selector {
	display: flex;
	align-items: center;
}

.shift-types-info {
	background: var(--el-fill-color-light);
	border: 1px solid var(--el-border-color-light);
	border-radius: 6px;
	padding: 12px;
}

.info-title {
	font-weight: 500;
	color: var(--el-text-color-primary);
	margin-bottom: 8px;
	font-size: 14px;
}

.shift-types-grid {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
}

.shift-type-item {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 8px 12px;
	background: var(--el-bg-color);
	border-radius: 4px;
	border: 1px solid var(--el-border-color-light);
}

.shift-type-color {
	width: 16px;
	height: 16px;
	border-radius: 50%;
	background: var(--shift-color);
	flex-shrink: 0;
}

.shift-type-info {
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.shift-type-name {
	font-weight: 500;
	font-size: 14px;
	color: var(--el-text-color-primary);
}

.shift-type-desc {
	font-size: 12px;
	color: var(--el-text-color-regular);
}

.loading-container {
	padding: 20px;
}

.schedule-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
	gap: 8px;
	margin-top: 16px;
}

.schedule-item {
	display: flex;
	flex-direction: column;
	align-items: center;
	padding: 8px;
	border: 1px solid var(--el-border-color-light);
	border-radius: 6px;
	text-align: center;
	cursor: pointer;
	transition: all 0.3s ease;
	background: var(--el-bg-color);
}

.schedule-item:hover {
	transform: translateY(-2px);
	box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.schedule-date {
	font-size: 12px;
	color: var(--el-text-color-regular);
	margin-bottom: 4px;
}

.schedule-type {
	font-size: 14px;
	font-weight: 500;
	margin-bottom: 2px;
}

.schedule-weekday {
	font-size: 10px;
	color: var(--el-text-color-placeholder);
}

.no-schedule {
	text-align: center;
	padding: 40px 20px;
	color: var(--el-text-color-placeholder);
}

/* 班次样式 - 使用更柔和的配色 */
.day-shift {
	background: linear-gradient(135deg, #f0f9ff, #e0f2fe);
	color: #0369a1;
	border-color: #0ea5e9;
}

.day-shift .schedule-type {
	color: #0369a1;
}

.night-shift {
	background: linear-gradient(135deg, #f8fafc, #f1f5f9);
	color: #475569;
	border-color: #64748b;
}

.night-shift .schedule-type {
	color: #475569;
}

.rest-day {
	background: linear-gradient(135deg, #faf5ff, #f3e8ff);
	color: #7c3aed;
	border-color: #8b5cf6;
}

.rest-day .schedule-type {
	color: #7c3aed;
}

.shift {
	background: linear-gradient(135deg, #ecfdf5, #d1fae5);
	color: #059669;
	border-color: #10b981;
}

.shift .schedule-type {
	color: #059669;
}

/* 暗黑模式下的班次样式 - 重新设计 */
html.dark {
	.day-shift {
		background: linear-gradient(135deg, #1e40af, #3b82f6);
		color: #dbeafe;
		border-color: #60a5fa;
		box-shadow: 0 2px 8px rgba(59, 130, 246, 0.3);
	}

	.day-shift .schedule-type {
		color: #ffffff;
		font-weight: 600;
	}

	.night-shift {
		background: linear-gradient(135deg, #7c3aed, #a855f7);
		color: #f3e8ff;
		border-color: #c084fc;
		box-shadow: 0 2px 8px rgba(124, 58, 237, 0.3);
	}

	.night-shift .schedule-type {
		color: #ffffff;
		font-weight: 600;
	}

	.rest-day {
		background: linear-gradient(135deg, #059669, #10b981);
		color: #d1fae5;
		border-color: #34d399;
		box-shadow: 0 2px 8px rgba(5, 150, 105, 0.3);
	}

	.rest-day .schedule-type {
		color: #ffffff;
		font-weight: 600;
	}

	.shift {
		background: linear-gradient(135deg, #dc2626, #ef4444);
		color: #fecaca;
		border-color: #f87171;
		box-shadow: 0 2px 8px rgba(220, 38, 38, 0.3);
	}

	.shift .schedule-type {
		color: #ffffff;
		font-weight: 600;
	}

	/* 暗黑模式下的整体样式优化 */
	.schedule-preview {
		background: #1a1a1a;
		border-color: #333;
		box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
	}

	.month-navigator {
		background: #2d2d2d;
		border-bottom-color: #404040;
	}

	.nav-btn {
		background: #4b5563;
		border-color: #4b5563;
	}

	.nav-btn:hover:not(:disabled) {
		background: #6b7280;
		border-color: #6b7280;
	}

	.quick-nav-btn {
		background: linear-gradient(135deg, #3b82f6, #60a5fa);
		box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2);
	}

	.quick-nav-btn:hover:not(:disabled) {
		background: linear-gradient(135deg, #2563eb, #3b82f6);
		box-shadow: 0 4px 15px rgba(59, 130, 246, 0.4);
		transform: translateY(-1px);
	}

	.schedule-item {
		background: #2d2d2d;
		border-color: #404040;
	}

	.schedule-item:hover {
		box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
		transform: translateY(-3px);
	}

	.schedule-date {
		color: #d1d5db;
	}

	.schedule-weekday {
		color: #9ca3af;
	}
}

/* 添加缺失的工具类 */
.mb-3 {
	margin-bottom: 12px;
}

.width100 {
	width: 100%;
}

/* 响应式设计 */
@media (max-width: 768px) {
	.schedule-grid {
		grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
		gap: 6px;
	}

	.schedule-item {
		padding: 6px;
	}

	.schedule-date {
		font-size: 10px;
	}

	.schedule-type {
		font-size: 12px;
	}
}

/* 只读模式下的月份显示样式 */
.readonly-month-display {
	display: flex;
	justify-content: center;
	padding: 16px;
	background: var(--el-fill-color-light);
	border-bottom: 1px solid var(--el-border-color-light);
}

.readonly-month-display .current-period {
	display: flex;
	align-items: center;
	gap: 8px;
}

.readonly-month-display .period-text {
	font-size: 18px;
	font-weight: 600;
	color: var(--el-text-color-primary);
}

.readonly-month-display .period-title {
	font-size: 16px;
	font-weight: 500;
	color: var(--el-text-color-regular);
}
</style>
